home *** CD-ROM | disk | FTP | other *** search
- ;---------------------------------------------------------------
- ;logcmd - command processing for device driver monitor |
- ;--------------------------------------------------------------|
- ;Copyright 1990, 1992 ASMicro Co. |
- ;--------------------------------------------------------------|
- ; |
- ; 4/15/90 Rick Knoblaugh |
- ;--------------------------------------------------------------|
- ;include files |
- ;---------------------------------------------------------------
- include logequ.inc
- include logstruc.inc
-
- code segment public 'CODE'
- assume cs:code, ds:code, es:code
- ;--------------------------------------------------------------
- ;PUBLIC |
- ;--------------------------------------------------------------
- public monitor_process
- public drv_open
- public drv_close
- public drv_ioctl_in
- public drv_ioctl_out
- public drv_non_supt
- public patch_flag
- public old_user_int
- public drv_state
- public save_patch
- public get_key
- public req_header
- public show_buffer
- public record_cmd
- public find_func
- public find_sub_func
- public config_dat
- public cmd_table
- public old_stack_ptr
- public old_stack_seg
- public logr_stack
- public logr_sp
- public prt_to_mem
- ;--------------------------------------------------------------
- include logdat.inc ;data for driver monitor
-
- ;--------------------------------------------------------------
- ;The following perform processing depending on what call into
- ;monitored device driver is occurring.
- ;--------------------------------------------------------------
- state_handlers dw process_nothing
- dw process_strat
- dw process_int
- dw process_ret
-
-
- out_table dw prt_to_null
- dw prt_to_printer
- dw prt_to_screen
- dw prt_to_mem
-
-
-
- drv_non_supt proc near
- mov ax, ERR_UNKNOWN
- ret
- drv_non_supt endp
-
- drv_open proc near
- drv_close proc near
- mov ax, OK_STATUS
- ret
- drv_close endp
- drv_open endp
-
- ;--------------------------------------------------------------
- ;drv_ioctl_out - receive from caller a far ptr to a user |
- ; buffer area in which to log data, and a dword|
- ; value containing the size in bytes of this |
- ; data area. |
- ;--------------------------------------------------------------
- drv_ioctl_out proc near
- les di, req_header ;get ptr to request header
- mov ax, ERR_GENFAIL ;default to error
- ;is this the number of bytes we are expecting?
- cmp es:[di].ioctl_count, size ioctl_out_data
- jne short drv_ioctl_o999 ;if not, error
- drv_ioctl_o100:
-
- les di, es:[di].ioctl_buf_ptr ;get ptr to DTA
- push ds
- lds bx, es:[di].user_buf_ptr ;get user's buffer ptr
- mov cs:user_data_ptr.d_offset, bx ;save it
- mov cs:user_data_ptr.d_segment, ds
-
- lds bx, es:[di].user_buf_size ;get size of buffer
- mov cs:user_data_size.d_offset, bx ;save it
- mov cs:user_data_size.d_segment, ds
-
- pop ds
-
- mov ax, OK_STATUS
- drv_ioctl_o999:
- ret
- drv_ioctl_out endp
-
- ;--------------------------------------------------------------
- ;drv_ioctl_in - pass back to caller, a far ptr to our count of|
- ; bytes written to user data area, offset of |
- ; our configuration info, and offset of our |
- ; command table info. |
- ; |
- ;--------------------------------------------------------------
- drv_ioctl_in proc near
- les di, req_header ;get ptr to request header
- mov es:[di].ioctl_count, size ioctl_in_data ;pass count
- les di, es:[di].ioctl_buf_ptr ;get ptr to DTA
-
- mov ax, offset wrk_data_count ;pass back pointer to
- ;our buffer count
- mov es:[di].drv_buf_count.d_offset, ax
- mov es:[di].drv_buf_count.d_segment, cs
-
- mov ax, offset config_dat
- mov es:[di].drv_config_dat, ax
- mov ax, offset cmd_table
- mov es:[di].drv_cmd_tbl, ax
-
- mov ax, OK_STATUS
- ret
-
- drv_ioctl_in endp
-
- ;--------------------------------------------------------------
- ;monitor_process |
- ;--------------------------------------------------------------
- monitor_process proc far
- cli
- mov cs:old_stack_ptr, sp
- mov cs:old_stack_seg, ss
- mov sp, cs
- mov ss, sp
- mov sp, offset cs:logr_sp
- sti
-
- cld
- push ds
- push es
- push ax
- push bx
- push cx
- push dx
- push di
- push si
-
- push cs ;get our ds
- pop ds
-
- mov di, drv_state
- shl di, 1
- ;
- ;Proccess based on which area of driver being monitored generated the
- ;user software interrupt.
- ;
- call word ptr [di + state_handlers]
-
-
- pop si
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- pop es
- pop ds
-
- cli
- mov sp, cs:old_stack_ptr
- mov ss, cs:old_stack_seg
- sti
- iret
- monitor_process endp
-
-
- process_nothing proc near
- ret
- process_nothing endp
-
-
-
- ;--------------------------------------------------------------
- ;process_strat - store the es:bx ptr to the request header |
- ; coming into the driver being monitored. Also|
- ; patch in an int instruction at start of |
- ; driver's interrupt routine. Set next state |
- ; to indicate next int should come from driver |
- ; interrupt routine. |
- ;--------------------------------------------------------------
- process_strat proc near
- mov mdrv_req_ptr.d_offset, bx ;save ptr to req header
- mov mdrv_req_ptr.d_segment, es
-
- les bx, dword ptr old_stack_ptr
- les di, dword ptr es:[bx].mdrv_off ;ptr to start of code
- mov mdrv_strat_ptr.d_segment, es
- ;
- ;Determine if the int instruction that gave us control was patched into
- ;the driver being monitored or is part of the driver source code. This
- ;is to decide where to return: at the instruction (replaced with former
- ;object code), or after the int instruction.
- ;
- cmp patch_flag, TRUE ;indicates that user patched
- jne process_s100
- sub di, 2 ;offset of int instruction
- ;
- ;When return occurs, control will pass back to code at int instruction
- ;which will be overlaid with the original code contents. Adjust the
- ;value on the stack.
- push ds
- lds bx, dword ptr old_stack_ptr ;get old ss and sp
- mov [bx].mdrv_off, di
- pop ds
-
- mov ax, save_patch ;get the original 2 bytes of code
- mov es:[di], ax ;put it back
-
-
- process_s100:
- mov mdrv_strat_ptr.d_offset, di
-
- ;
- ;Determine if address of interrupt routine for driver being monitored has
- ;been stored yet. If not, retrieve the address from the device driver
- ;header.
-
- cmp mdrv_int_ptr.d_segment, NULL
- jne process_s200
- mov mdrv_int_ptr.d_segment, es ;seg of int routine
- xor bx, bx ;offset header
- mov ax, es:[bx].dev_int
- mov mdrv_int_ptr.d_offset, ax ;offset of int routine
- process_s200:
- mov di, mdrv_int_ptr.d_offset
- ;
- ;Save first 2 bytes of code at the interrupt routine. Patch in the
- ;int instruction which will give us control.
-
- call save_n_patch
- mov drv_state, EXPECT_INT
-
- cmp header_flag, TRUE ;printed log header already?
- je process_s300
- call prt_log_hdr ;print name, load address etc.
-
- mov header_flag, TRUE
- process_s300:
- ret
- process_strat endp
-
-
-
- ;--------------------------------------------------------------
- ;process_int |
- ;--------------------------------------------------------------
- process_int proc near
- ;
- ;First, try to do a little checking to see if this is really the int routine.
- ;It's possible that the user of this program did not place the int which
- ;gives us control in the strategy routine. If things don't look like they
- ;should, simply return without attempting any monitoring.
- ;
- les bx, dword ptr old_stack_ptr
- les di, dword ptr es:[bx].mdrv_off ;&driver's int routine
- mov ax, es
- ;is this the segment we
- cmp ax, mdrv_int_ptr.d_segment ;are expecting?
- jne process_i999
- sub di, 2 ;back to "int" instruction
- cmp di, mdrv_int_ptr.d_offset
- jne process_i999
-
- inc drv_req_num ;count requests to driver
-
- ;Replace the int instruction with original contents
- ;
- call restor_instruc
-
- ;
- ;Fix value for the offset of where to return. Go back 2 bytes to location
- ;of int instruction.
- les bx, dword ptr old_stack_ptr
- mov es:[bx].mdrv_off, di ;put adjusted value back
- les di, dword ptr es:[bx].mdrv_ret_off
- ;
- ;Save ptr to where driver being monitored will return after its int routine
- ;completes.
- ;
- mov mdrv_ret_ptr.d_offset, di
- mov mdrv_ret_ptr.d_segment, es
- ;
- ;Save code at that location and patch in int instruction
- ;
- call save_n_patch
- mov drv_state, EXPECT_USE_RET
- cmp config_dat.show_cmd_blk, OUTPUT ;show only on return?
- je process_i999
-
- mov ax, drv_req_num ;exceeded number to log?
- cmp ax, config_dat.max_to_log
- ja process_i999 ;if yes, don't log any more
- ;
- ;Determine if the number of requests so far has reached the request number
- ;where the user wishes to start logging.
- ;
- cmp ax, config_dat.log_start_num
- jb process_i999
-
- mov si, offset entry_text
- call record_cmd ;go log request header etc.
- process_i999:
- ret
- process_int endp
-
-
- ;--------------------------------------------------------------
- ;process_ret |
- ;--------------------------------------------------------------
- process_ret proc near
- ;
- ;Compare location from which int was generated with the area we expected
- ;to generate it. If for some reason it isn't correct, simply return.
- les bx, dword ptr old_stack_ptr
- les di, dword ptr es:[bx].mdrv_off
- mov ax, es
-
- cmp ax, mdrv_ret_ptr.d_segment
- je process_r100
- jmp process_r999 ;far jump
- process_r100:
-
- sub di, 2 ;back to "int" instruction
- cmp di, mdrv_ret_ptr.d_offset ;offset we are expecting?
- je process_r120
- jmp process_r999
- process_r120:
- ;
- ;Replace the int instruction with original contents
- ;
- call restor_instruc
-
- ;Fix value for the offset of where to return back to 2 bytes to location
- ;of int instruction.
- les bx, dword ptr old_stack_ptr
- mov es:[bx].mdrv_off, di
- ;
- ;If user has patched user int into the driver being monitored, repatch that
- ;location.
- ;
- cmp patch_flag, TRUE
- jne process_r500
-
- les di, dword ptr mdrv_strat_ptr.d_offset
- ;
- ;Save code at that location and patch in int instruction.
- ;
- call save_n_patch
- process_r500:
- mov drv_state, EXPECT_STRAT
-
- ;Show command block only upon entry into the monitored device driver?
-
- cmp config_dat.show_cmd_blk, INPUT
- je process_r900
- mov ax, drv_req_num ;exceeded # commands to log?
- cmp ax, config_dat.max_to_log
- jbe process_r700
- jmp process_r999 ;if yes, don't log any more
- process_r700:
- ;
- ;Determine if the number of requests so far have reached the request number
- ;where the user wishes to start logging.
- ;
- cmp ax, config_dat.log_start_num
- jae process_r800
- jmp process_r999 ;far jump
- process_r800:
- mov si, offset exit_text ;"Exit"
- call record_cmd ;go log request header etc.
- process_r900:
- les bx, mdrv_req_ptr ;get ptr to request header
-
- cmp block_dev_flag, TRUE ;is this a block device?
- jne process_r950
-
- cmp es:[bx].req_hdr_cmd, CMD_INIT
- jne process_r910
-
- lds si, es:[bx].cmd0_bpb_ptr ;get ptr to BPB table
- mov si, [si] ;move from table to ptr
- jmp short process_r930
- process_r910:
- cmp es:[bx].req_hdr_cmd, CMD_BUILD_BPB
- jne process_r950
- lds si, es:[bx].cmd2_bpb_ptr ;get ptr to bpb table
- process_r930:
- mov ax, [si] ;get sector size
- mov cs:sector_size, ax ;save it
-
- push cs
- pop ds ;get local ds
- process_r950:
-
- cmp log_it, FALSE ;if command not to be logged
- je process_r999
-
- push cs
- pop es ;es=seg of output buffer
-
-
- cmp io_table_ptr, NULL ;is this an I/O command?
- je process_r970
- call show_buffer ;if so, go display data
- process_r970:
- ;
- ;do command completion status stuff
-
- push es ;save print buffer seg
-
- les bx, mdrv_req_ptr ;ptr to request block
-
- mov bx, es:[bx].req_hdr_status ;get cmd status
-
- pop es
-
- push bx ;save cmd status
- mov si, offset cmd_com_text ;"Command completion "
- call put_til_null
- test bx, ERR_BIT ;error?
- jnz process_r980 ;if so, go get error code
- mov si, offset success_text
- jmp short process_r990
-
- process_r980:
- and bx, 00ffh ;get return code portion only
- cmp bl, MAX_ERR ;out of range of error codes?
- jbe process_r985
- mov si, offset err_msg16 ;unknown error code message
- jmp short process_r990
- process_r985:
- shl bx, 1
- mov si, [bx + err_msg_ptrs]
-
- process_r990:
- call put_and_skip ;print status
- pop bx ;cmd status
- test bx, ERR_BIT ;error?
- jz process_r999 ;if no error, return
-
- cmp config_dat.wait_key_err, TRUE ;stop on errors?
- jne process_r999
-
- mov si, offset stop_msg
- call put_and_skip
- call get_key
-
-
- process_r999:
- ret
- process_ret endp
-
- ;--------------------------------------------------------------
- ;show_buffer - Called just after driver's interrupt routine |
- ; completes and it has been determined that the |
- ; command processed was an I/O command. |
- ; |
- ; Check user configured options for displaying |
- ; I/O buffers (e.g. show only reads, etc.) |
- ; If configured to display buffers for this |
- ; type of command, write the data. |
- ; |
- ; |
- ; Enter: ds = our local data |
- ; di = offset into output buffer |
- ; |
- ; Exit: di = offset of next output buffer |
- ; position. |
- ; Save ds register |
- ;--------------------------------------------------------------
- show_buffer proc near
- push ds
- les bx, mdrv_req_ptr ;get pointer to cmd
- cmp func_req_ptr.d_segment, NULL
- je show_b100
- ;
- ;if command has a function, get ptr to it.
- ;
- les bx, func_req_ptr ;get pointer to cmd
-
- show_b100:
-
- ;See if block size is indicated in the command (with MSCDEX,
- ;cooked or raw dictates block size).
- ;
- mov si, io_table_ptr ;get ptr to i/o info
- cmp [si].io_bs_indic, TRUE
- je show_b200 ;use BPB block size
- ;(1 byte if char)
-
- add bx, [si].io_off_indic ;point to cmd block byte
- ;that tells size
- add si, size io_table ;get to optional table elements
-
- show_b150:
- mov al, [si].io_bs_value ;get value that tells blk size
- cmp es:[bx], al ;match with cmd req blk value?
- je show_b180
- cmp al, TABLE_TERM ;cmd block not right?
- jne show_b170
- jmp show_b999 ;far jump to exit
- show_b170:
- add si, size io_bs_elements ;get to next value to match
- jmp short show_b150
- show_b180:
- mov ax, [si].io_bs
- mov sector_size, ax
- mov bx, mdrv_req_ptr.d_offset ;point back to start cmd blk
- cmp func_req_ptr.d_segment, NULL
- je show_b190
- mov bx, func_req_ptr.d_offset ;point back to
- ;start of cmd block
- show_b190:
- mov si, io_table_ptr ;get ptr to i/o info
- show_b200:
- push bx ;save start of cmd buffer
- add bx, [si].io_count
- mov ax, es:[bx] ;get count
- pop bx
- mov sector_count, ax
- add bx, [si].io_buf_ptr_off
-
- cmp [si].io_type, INPUT ;is this input or output?
- jne show_b210
-
- cmp config_dat.show_buf_in, TRUE ;show input buffers?
- jne show_b999
-
- mov ax, config_dat.max_show_in ;get max configured to show
- mov max_blocks, ax
- jmp short show_b230
- show_b210:
- cmp config_dat.show_buf_out, TRUE ;show output buffers?
- jne show_b999
-
- mov ax, config_dat.max_show_out ;max configured to show
- mov max_blocks, ax
- show_b230:
- mov block_count, 1 ;start counting the blocks
-
- push es ;save segment of cmd block
-
- push cs
- pop es ;es=seg of output buffer
-
- call skip_line
- mov si, offset data_buf_text
- call put_and_skip
-
- pop es
-
- lds si, es:[bx] ;get ptr to i/o buffer
-
- push cs
- pop es ;get es = local data
-
- show_b240:
- mov bx, cs:sector_count ;get number of chars or blocks
- cmp cs:sector_size, 1 ;doing characters?
- je show_b250
- show_b245:
- mov ax, cs:max_blocks
- cmp cs:block_count, ax ;showed maximum desired?
- ja show_b999
- call put_out_block
-
- mov bx, cs:sector_size
- show_b250:
-
- call dump_n_count
-
- cmp cs:sector_size, 1 ;doing characters?
- je show_b999 ;then done
-
- call skip_line
- dec cs:sector_count
- jz show_b999
- inc cs:block_count
- jmp short show_b245
-
- show_b999:
- pop ds
- ret
- show_buffer endp
-
-
- ;--------------------------------------------------------------
- ;put_out_block - print "block " and block number. |
- ; |
- ; Enter: block_count contains number |
- ; Save ds, si registers |
- ;--------------------------------------------------------------
- put_out_block proc near
- push ds
- push si
-
- push cs
- pop ds ;get ds=our local data
- mov si, offset block_text
- call put_til_null
- mov ax, block_count
- call out_int
- call term_line
- call out_line
- call skip_line
-
- pop si
- pop ds
- ret
- put_out_block endp
-
-
-
- ;--------------------------------------------------------------
- ;restor_instruc - replace the 2 bytes of code where int |
- ; instruction had been patched in. |
- ; |
- ; Enter: es:di location to be patched |
- ;--------------------------------------------------------------
- restor_instruc proc near
- mov ax, save_code
- mov es:[di], ax ;put it into the code
- ret
- restor_instruc endp
-
- ;--------------------------------------------------------------
- ;save_n_patch - Save the 2 bytes of code where int instruction|
- ; is to be placed. Place int instruction in |
- ; the code. |
- ; |
- ; Enter: es:di = location to be patched |
- ;--------------------------------------------------------------
- save_n_patch proc near
- mov ax, (USER_INT shl 8) or INT_OP_CODE
- xchg ax, es:[di]
- mov save_code, ax
- ret
- save_n_patch endp
-
- ;--------------------------------------------------------------
- ;record_cmd - Make call to do table lookup on command. Also, |
- ; determine if this type of command is to be |
- ; logged. If to be logged, write out the |
- ; description of the command and dump the cmd |
- ; request block (and any "packet" area). |
- ; |
- ; Enter: ds = our local data |
- ; si = offset of string indicating if |
- ; we are examining the cmd request |
- ; on "Entry" to or "Exit" from the |
- ; driver's interrupt routine. |
- ; |
- ; Exit: di = next offset in output buffer. |
- ; |
- ; DS register saved. |
- ;--------------------------------------------------------------
- record_cmd proc near
- les bx, mdrv_req_ptr ;ptr to request block
- push si ;save ptr to "Entry" or "Exit"
- call find_func
- mov bx, si ;save ptr to cmd table
- pop si
- mov di, offset out_buf
- cmp log_it, FALSE ;don't log this command?
- je record_c900
-
- push ds
- pop es ;get es = local ds
-
- call skip_line
- call put_til_null ;output "Entry" or "Exit"
- mov si, offset driv_req_text
- call put_til_null ;output "Driver request"
- mov ax, drv_req_num
- call out_int ;output sequence number
- mov si, bx ;si = ptr to cmd info table
- call out_descrip ;output command description
- ;
- ;si contains offset of cmd info table entry
- ;
- call prt_req ;print cmd request block
- cmp byte ptr [si].ri_func_ptr, NULL ;a function?
- je record_c900
- call skip_line
-
-
- mov bx, hold_sub_det_ptr ;get fuction table offset
- mov si, [bx].fd_descrip ;function description
- call put_and_skip ;go print it
-
- mov bl, [bx].fd_packet_len ;length of function packet
- sub bh, bh
- push ds
- lds si, func_req_ptr
- call dump_n_count
- call skip_line
- pop ds
-
- record_c900:
- ret
- record_cmd endp
-
- ;--------------------------------------------------------------
- ;find_func - Find the command requested in the table of |
- ; command information. Also, determine if |
- ; requested command should be logged. |
- ; |
- ; Enter: es:bx = ptr to function request |
- ; |
- ; Exit: si = offset of table entry |
- ;--------------------------------------------------------------
-
- find_func proc near
- mov al, es:[bx].req_hdr_cmd
- ;
- ;Search through a table of commands. Since some drivers such as those
- ;used with MSCDEX use nonsequential command codes, we can't simply index
- ;into the table.
- ;
- mov si, offset cmd_table
- find_func100:
- cmp al, [si].ri_cmd_code ;found?
- je find_func500
- cmp byte ptr [si].ri_cmd_code, TABLE_TERM ;not found?
- je find_func500
- add si, size req_info ;advance to next entry
- jmp short find_func100
-
- find_func500:
- mov ax, [si].ri_iotbl_ptr
- mov io_table_ptr, ax ;save I/O table information
-
- mov ax, NULL
- mov func_req_ptr.d_segment, ax ;default to no function
- mov func_req_ptr.d_offset, ax
-
- cmp [si].ri_func_ptr, ax ;is there a function?
- je find_func600
-
- push si
- mov si, [si].ri_func_ptr ;ptr to function table
- call find_sub_func ;return bx = function
- ;detail info table entry
- pop si
-
- find_func600:
-
- mov log_it, TRUE ;default to logging
- cmp config_dat.log_all, TRUE
- je find_func900
-
- cmp byte ptr [si].ri_log_flag, FALSE
- je find_func800
-
- cmp [si].ri_func_ptr, NULL ;is there a function?
- je find_func900
-
-
- cmp byte ptr [bx].fd_log_flag, TRUE ;log this function?
- je find_func900
- find_func800:
-
- mov log_it, FALSE ;don't log this command
- find_func900:
- ret
- find_func endp
-
-
-
-
- ;--------------------------------------------------------------
- ;find_sub_func - find detailed function table entry for |
- ; command. |
- ; |
- ; Enter: ds:si = ptr to function table |
- ; es:bx = ptr to command request block |
- ; |
- ; Exit: bx = offset of detailed function |
- ; table entry. |
- ;--------------------------------------------------------------
- find_sub_func proc near
- push di
- push es
-
- push es
- push bx ;save ptr to cmd req block
-
- add bx, [si].f_off_ptr
- les bx, es:[bx] ;get ptr to function
-
- mov func_req_ptr.d_segment, es ;save it
- mov func_req_ptr.d_offset, bx
-
- pop bx
- pop es ;restore ptr to cmd req block
-
-
-
- cmp byte ptr [si].f_sub_in, TRUE ;is function code
- ;here or pointed to?
- je find_sub_f100
-
- add bx, [si].f_off_ptr
- les bx, es:[bx] ;get ptr to function
-
-
-
- find_sub_f100:
- ;
- ;es:bx holds ptr to start of command block (or subcommand block). Determine
- ;where major code and minor code (if any) are found within cmd block.
- ;
- mov di, [si].f_off_cat_code
- mov al, es:[bx + di] ;get major code
- mov ah, NULL ;default to no minor code
- cmp [si].f_off_fun_code, NULL ;no minor code?
- je find_sub_f200
-
- mov di, [si].f_off_fun_code
- mov ah, es:[bx + di] ;get minor code
-
-
- find_sub_f200:
- mov bx, offset [si].f_detail_ptr ;get ptr to detailed info
- find_sub_f300:
- cmp ax, word ptr [bx].fd_cat_code ;codes found in table?
- je find_sub_f600
-
- find_sub_f500:
- cmp byte ptr [bx].fd_cat_code, TABLE_TERM ;not found?
- je find_sub_f600
- add bx, size func_detail ;advance to next entry
- jmp short find_sub_f300
- find_sub_f600:
- mov ax, [bx].fd_iotbl_ptr
- mov io_table_ptr, ax ;save io table information
- mov hold_sub_det_ptr, bx
- pop es
- pop di
-
- ret
- find_sub_func endp
-
-
- ;--------------------------------------------------------------
- ; out_int - format a nonzero binary number to ASCII and |
- ; place formatted number into output buffer. |
- ; |
- ; Enter: ax = binary number. |
- ; es:di = ptr to output buffer. |
- ; |
- ; Exit: di = next offset in output buffer. |
- ;--------------------------------------------------------------
-
- out_int proc near
- push bx
- push cx
- push si
- add di, 4
- mov si, di ;advance to last digit
- mov cx, 5 ;5 digits
- mov bx, 10 ;divide by 10
- out_i100:
- xor dx, dx
- div bx
- add dl, '0' ;make ASCII
- or ax, ax
- jnz out_i200
- cmp dl, '0'
- jne out_i200
- mov dl, ' ' ;no leading zeros
- out_i200:
- mov es:[si], dl ;get remainder
- dec si
- loop out_i100
- add di, 8 ;need some space after number
-
- pop si
- pop cx
- pop bx
- ret
- out_int endp
-
-
-
- out_descrip proc near
- push si
- mov si, [si].ri_descrip ;get ptr to cmd description
- call put_and_skip ;print it
- pop si
- ret
- out_descrip endp
-
-
-
-
-
- get_key proc near
- sub ah, ah
- int 16h
- ret
- get_key endp
-
-
-
- ;--------------------------------------------------------------
- ;prt_log_hdr - print the device name, type, and load address |
- ; to the configured output device. |
- ; |
- ; Enter: es = segment where driver is loaded. |
- ; ds = our local data. |
- ; |
- ; Exit: di = next offset in output buffer. |
- ;--------------------------------------------------------------
- prt_log_hdr proc near
- mov bx, offset block_text
- mov block_dev_flag, TRUE
-
- push es
- pop ds ;get ds=monitored driver's segment
-
- push cs
- pop es ;get es=local segment
-
- xor si, si
- test byte ptr [si].dev_attrib.w_msb, 80h ;char device?
- jz prt_log_h200
- mov di, offset es:head_drv_name
- mov cx, HEAD_DRV_NLEN
-
- mov si, size dev_header ;point to device name
- rep movsb ;move into buffer
-
- mov bx, offset es:char_text
- mov es:block_dev_flag, FALSE ;flag as a char device
-
-
- prt_log_h200:
- mov si, bx ;offset of device description
- push ds ;save monitored driver's segment
-
- push es
- pop ds ;ds = local data
-
- mov di, offset head_dev_type
- call put_til_null ;output heading line
- mov di, offset head_load
-
- pop ds ;restore driver segment
- xor si, si
- call format_seg
-
- push es
- pop ds
-
- mov di, offset out_buf
- push di
- mov si, offset head_line
- call put_til_null ;move heading into buffer
- call term_line
- pop di
- call out_line
- ret
- prt_log_hdr endp
-
-
- prt_req proc near
- push ds
- push si
- lds si, mdrv_req_ptr
- sub bh, bh
- mov bl, [si] ;get number of bytes
- call dump_n_count
- pop si
- pop ds
- ret
- prt_req endp
-
- ;--------------------------------------------------------------
- ;dump_n_count - do a dump of specified area. |
- ; |
- ; Enter: ds:si = ptr to area. |
- ; bx = number of bytes. |
- ; Exit: di = start of output buffer |
- ;--------------------------------------------------------------
- dump_n_count proc near
- call dump_a_line
- call out_line
- cmp bx, 10h
- jbe dump_n_c200
- sub bx, 10h
- jmp short dump_n_count
- dump_n_c200:
- ret
- dump_n_count endp
-
-
- ;--------------------------------------------------------------
- ;dump_a_line - given a ptr ds:si to a buffer, form 10h bytes |
- ; of dump data at es:di. |
- ;--------------------------------------------------------------
-
- dump_a_line proc near
- push di ;save start print buf
- call format_seg
- add di,2 ;leave some space
- mov cx, 10h
- push ds
- push si ;save start of data
- dump_a_l100:
- lodsb
- cmp si, 0 ;did offset just wrap?
- jne dump_a_l150
- mov ax, ds ;if so, get to new
- add ax, 1000h ;64k
- mov ds, ax
- dump_a_l150:
- call put_hex_dig
- cmp cl, 9
- jne dump_a_l200
- mov al, '-'
- mov es:[di],al
- dump_a_l200:
- inc di
- loop dump_a_l100
- pop si
- pop ds
- add di, 3
- mov cx, 10h
- dump_a_l250:
- lodsb
- cmp si, 0 ;did offset just wrap?
- jne dump_a_l260
- mov ax, ds ;if so, get to new
- add ax, 1000h ;64k
- mov ds, ax
- dump_a_l260:
- cmp al, ' '
- jae dump_a_l300
- mov al, '.'
- dump_a_l300:
- stosb
- loop dump_a_l250
- call term_line
- pop di
- ret
- dump_a_line endp
-
- clear_line proc near
- push di
- mov cx, 40
- mov ax, ' '
- rep stosw
- pop di
- ret
- clear_line endp
-
- ;--------------------------------------------------------------
- ;format_seg - format segment and offset in ds:si in ASCII |
- ; as follows: |
- ; xxxx:xxxx |
- ; Put into buffer from ptr es:di |
- ; |
- ; Exit: di = next offset in output buffer. |
- ;--------------------------------------------------------------
-
- format_seg proc near
- mov ax, ds ;do the segment
- mov cx, 2 ;2 words
- format_s100:
- xchg al, ah ;want to print MSB first
- mov dl, ah ;save LSB
- call put_hex_dig
- mov al, dl
- call put_hex_dig
- mov al, ':'
- stosb
- mov ax, si ;do the offset
- loop format_s100
- mov byte ptr es:[di - 1], ' ' ;ignore last ':'
- ret
- format_seg endp
-
-
-
-
- ;--------------------------------------------------------------
- ;out_line - print line at cs:out_buf. Reset di to beginning. |
- ; |
- ;--------------------------------------------------------------
- out_line proc proc
- push bx
- push si
- push ds
-
- push cs
- pop ds ;get ds = cs
- mov di, offset out_buf
- mov si, di
- mov bx, config_dat.output_device
- shl bx, 1 ;get command code
- call word ptr [bx + out_table]
- call clear_line
-
- pop ds
- pop si
- pop bx
- ret
- out_line endp
-
-
-
-
-
-
- prt_to_null proc near
- ret
- prt_to_null endp
-
-
- prt_to_screen proc near
- mov ah, 14 ;teletype
- mov bl, 0fh ;intense white
- lodsb
- or al, al ;end of data?
- jz ptr_to_sc900
- int 10h
- jmp short prt_to_screen
- ptr_to_sc900:
- ret
- prt_to_screen endp
-
- prt_to_printer proc near
- mov dx, LPT1
- ptr_to_pr100:
- mov ah, 0 ;print char
- lodsb
- or al, al ;end of data?
- jz ptr_to_pr900
- int 17h
- jmp short ptr_to_pr100
- ptr_to_pr900:
- ret
- prt_to_printer endp
-
- prt_to_mem proc near
- push di ;save buffer ptr
- push es
- les di, user_data_ptr ;get user's buf ptr
- mov ax, es
- cmp ax, NULL ;has user made IOCTL yet?
- je prt_to_mi900 ;if not, can't write
-
- les di, wrk_data_ptr ;get working ptr
- ;
- ;Has user reset the buffer count? If so, set work pointer to start of
- ;user buffer.
-
- cmp wrk_data_count.d_segment, 0
- ja prt_to_mi100
-
- cmp wrk_data_count.d_offset, 0
- ja prt_to_mi100
-
- les di, user_data_ptr
- mov wrk_data_ptr.d_offset, di
- mov wrk_data_ptr.d_segment, es
-
- prt_to_mi100:
- mov dx, user_data_size.d_segment ;is user buffer full?
- cmp dx, wrk_data_count.d_segment
- ja prt_to_mi120
-
- mov dx, user_data_size.d_offset
- cmp dx, wrk_data_count.d_offset
- ja prt_to_mi120
- jmp short prt_to_mi900 ;if so, can't write
- prt_to_mi120:
- movsb
-
- cmp di, 0 ;did we just wrap?
- jne prt_to_mi150
-
- mov ax, es ;if so, get to new
- add ax, 1000h ;64k
- mov es, ax
-
- prt_to_mi150:
- inc wrk_data_count.d_offset
- jnz prt_to_mi200
- inc wrk_data_count.d_segment
-
- prt_to_mi200:
- cmp byte ptr [si], NULL ;end of line?
- jne prt_to_mi100 ;if not, continue
-
-
- prt_to_mi900:
-
- mov wrk_data_ptr.d_offset, di ;save where left off
- mov wrk_data_ptr.d_segment, es
-
- pop es
- pop di
- ret
- prt_to_mem endp
-
- skip_line proc near
- mov word ptr cs:[di], (CR SHL 8) OR LF
- add di, 2
- ret
- skip_line endp
-
- term_line proc near
- call skip_line
- mov byte ptr cs:[di], NULL
- inc di
- ret
- term_line endp
-
-
- put_til_null proc near
- lodsb
- or al, al
- jz put_til_900
- stosb
- jmp short put_til_null
- put_til_900:
- ret
- put_til_null endp
-
- put_and_skip proc near
- call put_til_null ;put it in buffer
- call term_line
- call out_line ;print it
- call skip_line
- ret
- put_and_skip endp
-
- put_hex_dig proc near
- push cx
- mov cx, 2 ;2 digits in al
- mov ah, al
- put_hex_100:
- shr al, 1
- shr al, 1
- shr al, 1
- shr al, 1
- cmp al, 9
- ja put_hex_500
- add al, '0'
- jmp short put_hex_900
- put_hex_500:
- add al, 'A' - 10
- put_hex_900:
- stosb
- mov al, ah
- shl al, 1
- shl al, 1
- shl al, 1
- shl al, 1
- loop put_hex_100
- pop cx
- ret
-
- put_hex_dig endp
-
-
- out_buf db 256 dup(' ')
- end_out_buf EQU $ - out_buf
-
-
- code ends
- end